package com.borened.common.core.util;

import com.borened.common.core.base.TreeSelectVO;
import com.borened.common.core.base.Treeifyable;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Treeifyable 树实体操作工具类, N为具体的树形实体类
 * <p>
 * 便于在代码中灵活使用该工具，暂不交给spring管理。
 * </p>
 *
 * @author: cch
 * @since: 2021/12/22
 */
public class TreeTool<N extends Treeifyable<N>> {

    /**
     * <p>
     * 从所给节点列表构建 前端需要的 树形结构数据
     * {@link TreeSelectVO#TreeSelectVO(Treeifyable)}
     * </p>
     *
     * @param nodes 待构建列表
     * @return java.util.List<TreeSelectVO>
     */
    public List<TreeSelectVO> buildTreeSelect(List<N> nodes) {
        //构建部门树
        List<N> nodesTree = buildTree(nodes);

        return nodesTree.stream().map(TreeSelectVO::new).collect(Collectors.toList());
    }

    /**
     * 从所给元数据列表构建 树形数据
     *
     * @param nodes
     * @return
     */
    public List<N> buildTree(List<N> nodes) {
        List<N> returnList = new ArrayList<>();
        List<String> tempList = new ArrayList<>();
        for (N node : nodes) {
            tempList.add(node.getNodeId());
        }
        for (N res : nodes) {
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(res.getParentNodeId())) {
                recursionFn(nodes, res);
                returnList.add(res);
            }
        }
        if (returnList.isEmpty()) {
            returnList = nodes;
        }
        return returnList;
    }

    /**
     * 获取子节点id集合
     *
     * @param node
     * @param list
     * @return
     */
    public List<String> getChildNodeIds(N node, List<N> list) {
        List<String> resultList = new ArrayList<>();
        recursionFnAddChild(resultList, list, node);
        return resultList;
    }

    private void recursionFnAddChild(List<String> resultList, List<N> sourceList, N node) {
        // 得到子节点列表
        List<N> childList = getChildList(sourceList, node);
        //添加本级儿子id
        resultList.addAll(childList.stream().map(Treeifyable::getNodeId).collect(Collectors.toList()));
        for (N child : childList) {
            if (hasChild(sourceList, child)) {
                recursionFnAddChild(resultList, sourceList, child);
            }
        }

    }

    /**
     * 递归列表
     *
     * @param list
     * @param node
     */
    private void recursionFn(List<N> list, N node) {
        // 得到子节点列表
        List<N> childList = getChildList(list, node);
        node.setChildNodes(childList);
        for (N tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * @param list 待选列表
     * @param node 要查询子节点的资源
     *             得到子节点列表
     */
    private List<N> getChildList(List<N> list, N node) {
        List<N> tlist = new ArrayList<>();
        for (N n : list) {
            if (n.getParentNodeId().trim().equals(node.getNodeId().trim())) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<N> list, N node) {
        return getChildList(list, node).size() > 0;
    }
}
